`include "common_def.v"
module MODULE_IF_ID( 
	input									clk_i	,	
	input									rst_i	,	
	input									if_valid_i,
	input									id_ready_i,
	output								write_pr_en_o,
	output								pc_change_start_o,
	output								if_start_o,
	output								id_start_o,
	input									stop_i,
	input									wash_i,
	input									add_nouse_inst_i,
	input									add_start_i,
	output								pc_recover_o,
	input									is_fencei_i,
	input									fencei_end_add_start_i,

	input		[31:0]				inst_i,	
	input		[`WIDTH-1:0]		pc_i	,	
	output		[31:0]				inst_o,	
	output		[`WIDTH-1:0]		pc_o		
);

//generate the write_regs_en singnal
//the if_valid_i will only stay high for onecyle
//the id_ready_i will always stay high if id is ready
wire if_valid;
Reg #(1,0) if_valid_reg(clk_i,rst_i,id_ready_i ? 1'b0:if_valid_i,if_valid,if_valid_i|id_ready_i);
wire write_regs_en;

assign write_regs_en = (if_valid|if_valid_i)&id_ready_i&(~stop_i)&(~add_nouse_inst_i)&(~is_fencei_i);
assign write_pr_en_o = write_regs_en;
//通常情况下就是由于跳转冲刷后或者pc改变后下一个周期启动取指令以及刚刚复位后启动一次。
//但是当处理冲突加入一条无用指令的时候既不让pc改变也不触发取指也不让当前指令开始译码。
//当add_nouse_inst_i 变为低后需要触发一次pc改变和取指和译码用add_nouse_inst_i的下降
//沿检测即可

//wire add_nouse_inst_r;
//wire add_start;
//Reg #(1,0) add_nouse_inst_reg(clk_i,rst_i,add_nouse_inst_i,add_nouse_inst_r,1);
//assign add_start = (~add_nouse_inst_i) & add_nouse_inst_r;

//id_start_o
wire id_start_r;
Reg #(1,0) id_start_o_reg(clk_i,rst_i,write_regs_en,id_start_r,1);
//assign id_start_o = (id_start_r &(~add_nouse_inst_i)) | add_start;
assign id_start_o = id_start_r;
//pc_change_start_o
wire	pc_change_start_r;
Reg #(1,0) pc_change_start_reg(clk_i,rst_i,(write_regs_en|add_start_i)&(~is_fencei_i)|fencei_end_add_start_i,pc_change_start_r,1);
assign pc_change_start_o = pc_change_start_r&(~add_nouse_inst_i)&(~is_fencei_i)|wash_i;
//if_start_o
wire if_start_first;
wire rst_delay_r;
wire rst_delay_r1;
wire if_start;
Reg #(1,0) rst_delay_reg(clk_i,rst_i,~rst_i,rst_delay_r,1);
Reg #(1,0) rst_dealy_reg1(clk_i,rst_i,rst_delay_r,rst_delay_r1,1);
assign if_start_first = rst_delay_r &(~rst_delay_r1);
Reg #(1,0) if_start_reg (clk_i,rst_i,pc_change_start_o| wash_i,if_start,1);
assign if_start_o = if_start|if_start_first;
//pc_recover_o
assign pc_recover_o = (if_valid|if_valid_i)&id_ready_i&(~stop_i)&add_nouse_inst_i;

//regs for save signals
Reg#(32,0) reg_inst_o(clk_i,rst_i,wash_i|fencei_end_add_start_i ?0:inst_i,inst_o,write_regs_en|wash_i|fencei_end_add_start_i);	
Reg#(`WIDTH,`RST_PC) reg_pc_o(clk_i,rst_i,wash_i?0:pc_i,pc_o,write_regs_en|wash_i);		

endmodule
